#lang sicp
(define (make-table same-key?)
  (let ((table (list '*table*)))
    (define (assoc se key)
      (cond ((null? se) #F)
            ((same-key? key (caar se)) (car se))
            (else
             (assoc (cdr se) key))))
    (define (lookup key1 key2)
      (let ((subtable (assoc (cdr table) key1)))
        (if subtable
            (let ((record (assoc (cdr subtable) key2)))
              (if record
                  (cdr record)
                  #F))
            #F)))
    (define (insert! key1 key2 value)
      (let ((subtable (assoc (cdr table) key1)))
        (if subtable
            (let ((record (assoc (cdr subtable) key2)))
              (if record
                  (set-cdr! record value)
                  (set-cdr! subtable
                            (cons (cons key2 value)
                                  (cdr subtable)))))
            (set-cdr! table
                      (cons (list key1 (cons key2 value))
                            (cdr table)))))
      'ok)
    (define (dispatch msg)
      (cond ((eq? msg 'lookup-proc) lookup)
            ((eq? msg 'insert-proc!) insert!)
            (else (error "unknown message! -- MAKE-TABLE" msg))))
    dispatch))


(define (same-key? a b)
  (if (and (number? a)
           (number? b))
      (<= (abs (- a b)) 5)
      (equal? a b)))

(define operation-table (make-table same-key?))
(define get (operation-table 'lookup-proc))
(define put (operation-table 'insert-proc!))